package com.sky.aop;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect // 这个类就变成了切面类
@Component
public class AutoFillAop {
   private static final Logger log = LoggerFactory.getLogger(AutoFillAop.class);

   //切点
   @Pointcut("@annotation(com.sky.annotation.AutoFill)")
   public void pt1() {
   }

   @Before("pt1()")
   public void fillProperty(JoinPoint joinPoint) {
      log.info("开始进行公共字段自动填充...");

      //获取到当前被拦截的方法上的数据库操作类型
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
      AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
      OperationType operationType = autoFill.value();//获得数据库操作类型

      //获取到当前被拦截的方法的参数--实体对象
      Object[] args = joinPoint.getArgs();
      if(args == null || args.length == 0){
         return;
      }

      Object entity = args[0];

      //准备赋值的数据
      LocalDateTime now = LocalDateTime.now();
      Long currentId = BaseContext.getCurrentId();

      //根据当前不同的操作类型，为对应的属性通过反射来赋值
      if(operationType == OperationType.INSERT){
         //为4个公共字段赋值
         try {
            Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

            //通过反射为对象属性赋值
            setCreateTime.invoke(entity,now);
            setCreateUser.invoke(entity,currentId);
            setUpdateTime.invoke(entity,now);
            setUpdateUser.invoke(entity,currentId);
         } catch (Exception e) {
            e.printStackTrace();
         }
      }else if(operationType == OperationType.UPDATE){
         //为2个公共字段赋值
         try {
            Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

            //通过反射为对象属性赋值
            setUpdateTime.invoke(entity,now);
            setUpdateUser.invoke(entity,currentId);
         } catch (Exception e) {
            e.printStackTrace();
         }
      }
   }
}
